package com.gitee.cashzhang27.test.cloud.oauth.auth.server.extended.handler;

import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.CharsetUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import lombok.Builder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.exceptions.InvalidClientException;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.OAuth2Request;
import org.springframework.security.oauth2.provider.TokenRequest;
import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestValidator;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;

/**
 * @author Cash Zhang
 * @version v1.0
 * @since 2019/02/26 22:37
 */
@Slf4j
@Builder
public class LoginSuccessHandler implements AuthenticationSuccessHandler {

  private ObjectMapper objectMapper;
  private PasswordEncoder passwordEncoder;
  private ClientDetailsService clientDetailsService;
  private AuthorizationServerTokenServices defaultAuthorizationServerTokenServices;

  @Override
  public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
      Authentication authentication) {

    try {
      String clientId = request.getParameter("client_id");
      String clientSecret = request.getParameter("client_secret");
      String grantType = request.getParameter("grant_type");

      ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId);

      //校验secret
      if (!passwordEncoder.matches(clientSecret, clientDetails.getClientSecret())) {
        throw new InvalidClientException("Given client ID does not match authenticated client");

      }

      TokenRequest tokenRequest = new TokenRequest(MapUtil.newHashMap(), clientId,
          clientDetails.getScope(), grantType);

      //校验scope
      new DefaultOAuth2RequestValidator().validateScope(tokenRequest, clientDetails);
      OAuth2Request oAuth2Request = tokenRequest.createOAuth2Request(clientDetails);
      OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(oAuth2Request,
          authentication);
      OAuth2AccessToken oAuth2AccessToken = defaultAuthorizationServerTokenServices
          .createAccessToken(oAuth2Authentication);
      log.info("获取token 成功：{}", oAuth2AccessToken.getValue());

      response.setCharacterEncoding(CharsetUtil.UTF_8);
      response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
      PrintWriter printWriter = response.getWriter();
      printWriter.append(objectMapper.writeValueAsString(oAuth2AccessToken));
    } catch (IOException e) {
      throw new BadCredentialsException(
          "Failed to decode basic authentication token");
    }

  }


}
